home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / toswinsc.zoo / config.c next >
Encoding:
C/C++ Source or Header  |  1992-10-27  |  15.6 KB  |  807 lines

  1. /*
  2.  * Copyright 1992 Eric R. Smith. All rights reserved.
  3.  * Redistribution is permitted only if the distribution
  4.  * is not for profit, and only if all documentation
  5.  * (including, in particular, the file "copying")
  6.  * is included in the distribution in unmodified form.
  7.  * THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTY, NOT
  8.  * EVEN THE IMPLIED WARRANTIES OF MERCHANTIBILITY OR
  9.  * FITNESS FOR A PARTICULAR PURPOSE. USE AT YOUR OWN
  10.  * RISK.
  11.  */
  12. #include <ctype.h>
  13. #include <string.h>
  14. #include <osbind.h>
  15. #include <stdlib.h>
  16. #include "xgem.h"
  17. #include "toswin.h"
  18. #include "filbuf.h"
  19. #include "twdefs.h"
  20. #include "twproto.h"
  21.  
  22. #define LASTMENU ((MENU *)0)
  23.  
  24. #define QUOTE '\"'
  25. #define LINSIZ 256
  26. #define WORDSIZ 128
  27.  
  28.  
  29. char *
  30. nextword(ptr)
  31.     char **ptr;
  32. {
  33.     char *s, *start;
  34.  
  35.     s = *ptr;
  36.     while (*s && isspace(*s))
  37.         s++;
  38.     start = s;
  39.     if (*s == QUOTE) {
  40.         start++; s++;
  41.         while (*s && *s != QUOTE) s++;
  42.     } else {
  43.         while (*s && !isspace(*s))
  44.             s++;
  45.     }
  46.     if (*s)
  47.         *s++ = 0;
  48.     *ptr = s;
  49.     return start;
  50. }
  51.  
  52. int
  53. hexval(s)
  54.     char *s;
  55. {
  56.     int val = 0;
  57.     int c, i;
  58.  
  59.     for (i = 12; i >= 0; i -= 4) {
  60.         c = *s++;
  61.         c = toupper(c);
  62.         if (c >= '0' && c <= '9') {
  63.             val |= ((c - '0') << i);
  64.         } else if (c >= 'A' && c <= 'F') {
  65.             val |= ((c - 'A') + 10) << i;
  66.         } else {
  67.             break;
  68.         }
  69.     }
  70.     return val;
  71. }
  72.  
  73. char *
  74. valhex(i)
  75.     int i;
  76. {
  77.     static char sbuf[5];
  78.     char *s;
  79.     int c;
  80.  
  81.     for (s = &sbuf[3]; s >= sbuf; --s) {
  82.         c = i & 0x000f;
  83.         i = i >> 4;
  84.         if (c >= 0 && c <= 9) {
  85.             *s = c + '0';
  86.         } else {
  87.             *s = (c - 10) + 'A';
  88.         }
  89.     }
  90.     return sbuf;
  91. }
  92.  
  93. int
  94. decval(s)
  95.     char *s;
  96. {
  97.     int i = 0;
  98.     int c;
  99.  
  100.     while ((c = *s++)) {
  101.         if (c < '0' || c > '9') break;
  102.         i = 10 * i + (c - '0');
  103.     }
  104.     return i;
  105. }
  106.  
  107. char *
  108. valdec(i)
  109.     int i;
  110. {
  111.     static char foo[4];
  112.     char *s;
  113.     int d;
  114.  
  115.     s = foo;
  116.     if (i >= 0 && i < 1000) {
  117.         d = i / 100;
  118.         i = i % 100;
  119.         *s++ = '0'+d;
  120.         d = i / 10;
  121.         i = i % 10;
  122.         *s++ = '0'+d;
  123.         *s++ = '0'+i;
  124.     }
  125.     *s++ = 0;
  126.     return foo;
  127. }
  128.  
  129. /*
  130.  * like valdec, put strips leading '0' characters
  131.  */
  132.  
  133. char *
  134. valdec2(d)
  135.     int d;
  136. {
  137.     char *s;
  138.  
  139.     s = valdec(d);
  140.     while (*s == '0' && *(s+1) != 0)
  141.         s++;
  142.     return s;
  143. }
  144.  
  145. struct varstruct {
  146.     char *name;
  147.     int  *addr;
  148. } vars[] = {
  149.     "altcol", &altcol,
  150.     "altrow", &altrow,
  151.     "altscroll", &altscroll,
  152.     "align", &align_windows,
  153.     "appmenus", &appl_menus,
  154.     "autoclose", &autoclose,
  155.     "cut", &cut_options,
  156.     "defaultgadgets", &default_kind,
  157.     "environ", &env_options,
  158.     "flourishes", &win_flourishes,
  159.     "paste", &paste_options,
  160.     "point", &point_to_type,
  161.     "showtool", &showtools,
  162.     "smoothscroll", &smoothscroll,
  163.     "stdcol", &stdcol,
  164.     "stdrow", &stdrow,
  165.     "stdscroll", &stdscroll,
  166.     0, 0
  167. };
  168.  
  169. /* adjust "font" and "height" to match (as closely as possible) a font
  170.  * setting in the global variable "fontdesc"; if a match can't be
  171.  * found, try the default font
  172.  */
  173.  
  174. static void
  175. adjust_font(font, height)
  176.     int *font, *height;
  177. {
  178.     FONTDESC *f, *dflt;
  179.     int i;
  180.  
  181.     dflt = 0;
  182.     f = fontdesc;
  183.     for (i = 0; i < gl_numfonts; i++) {
  184.         if (f->fontidx == *font && (f->points & (1L << *height)) )
  185.             return;        /* everything's OK */
  186.         else if (f->fontidx == default_font)
  187.             dflt = f;
  188.         f++;
  189.     }
  190.     *font = default_font;
  191.     if (dflt && (dflt->points & (1L << *height)))
  192.         return;        /* this height is OK */
  193.     *height = default_height;
  194. }
  195.  
  196. void
  197. set_default_font(s)
  198.     char *s;
  199. {
  200.     int font, size;
  201.  
  202.     font = hexval(nextword(&s));
  203.     size = hexval(nextword(&s));
  204.  
  205.     adjust_font(&font, &size);
  206.  
  207.     default_font = font;
  208.     default_height = size;
  209. }
  210.  
  211. static void
  212. adjust_xywh(xp, yp, wp, hp)
  213.     int *xp, *yp, *wp, *hp;
  214. {
  215.     int x = *xp;
  216.     int y = *yp;
  217.     int w = *wp;
  218.     int h = *hp;
  219.  
  220.     if (x + w > xdesk + wdesk) {
  221.         x = xdesk + wdesk - w;
  222.         if (x < xdesk) {
  223.             x = xdesk;
  224.             w = wdesk;
  225.         }
  226.     }
  227.     if (y + h > ydesk + hdesk) {
  228.         y = ydesk + hdesk - h;
  229.         if (y < ydesk) {
  230.             y = ydesk;
  231.             h = hdesk;
  232.         }
  233.     }
  234.     *xp = x; *yp = y;
  235.     *wp = w; *hp = h;
  236. }
  237.  
  238. void
  239. load_window(s)
  240.     char *s;
  241. {
  242.     int kind, flags, x, y, w, h, cols, rows, font, points;
  243.     int scroll;
  244.     char *title, *progname, *cmdlin, *progdir;
  245.     TEXTWIN *t;
  246.     WINDOW *v;
  247.  
  248.     flags = hexval(nextword(&s));
  249.     kind = hexval(nextword(&s));
  250.     x = hexval(nextword(&s));
  251.     y = hexval(nextword(&s));
  252.     w = hexval(nextword(&s));
  253.     h = hexval(nextword(&s));
  254.     cols = hexval(nextword(&s));
  255.     rows = hexval(nextword(&s));
  256.     font = hexval(nextword(&s));
  257.     points = hexval(nextword(&s));
  258.     title = nextword(&s);
  259.     progname = nextword(&s);
  260.     cmdlin = nextword(&s);
  261.     progdir = nextword(&s);
  262.     scroll = hexval(nextword(&s));
  263.  
  264.     adjust_font(&font, &points);
  265.     wind_calc(WC_BORDER, kind, x, y, w, h, &x, &y, &w, &h);
  266.     adjust_xywh(&x, &y, &w, &h);
  267.  
  268.     t = newproc(progname, cmdlin, progdir, x, y, cols, rows, scroll,
  269.             kind, font, points);
  270.     if (!t) return;
  271.     v = t->win;
  272.     wind_calc(WC_WORK, kind, x, y, w, h, &v->wi_x, &v->wi_y,
  273.         &v->wi_w, &v->wi_h);
  274.     title_window(v, title);
  275.     if (!oldACC)
  276.         open_window(v);
  277.     if (flags & WICONIFIED) {
  278.         iconify_win(v);
  279.     }
  280. }
  281.  
  282. extern int getfilename();
  283. static char config_name[128] = "TOSWIN.CNF";
  284. static char config_path[128];
  285.  
  286. void
  287. load_config(name)
  288.     char *name;
  289. {
  290.     FILBUF *f;
  291.     static char buf[LINSIZ];
  292.     char *s, *word;
  293.     struct varstruct *v;
  294.     ENTRY *e;
  295.     int *var;
  296.     int i;
  297.     int loadwins = 1;
  298.     int changepath = 1;
  299.  
  300.     if (!name) {            /* ask the user for a name */
  301.         name = buf;
  302.         i = getfilename(Strng(LOADCFG), name, config_path,
  303.                  config_name);
  304.         if (i != OK) return;
  305.         loadwins = 0;
  306.         changepath = 0;
  307.     }
  308.  
  309.     f = FBopen(name);
  310.     if (!f) return;
  311.  
  312.     graf_mouse(BEE, 0L);
  313.     while ((s = FBgets(f, buf, LINSIZ))) {
  314.         word = nextword(&s);
  315.         /* variable setting? */
  316.         for (v = vars; v->name; v++) {
  317.             if (!strcmp(v->name, word)) {
  318.                 word = nextword(&s);
  319.                 *v->addr = hexval(word);
  320.                 if (!strncmp(v->name, "std", 3))
  321.                     lineAset = 1;
  322.                 goto endloop;
  323.             }
  324.         }
  325.         if (!strcmp(word, "font")) {
  326.             set_default_font(s);
  327.         } else if (!strcmp(word, "path")) {
  328.             if (changepath)
  329.                 strcpy(progpath, nextword(&s));
  330.         } else if (!strcmp(word, "prog")) {
  331.             if (changepath)
  332.                 strcpy(dfltprog, nextword(&s));
  333.         } else if (!strcmp(word, "menu")) {
  334.             load_menu_key(s);
  335.         } else if (!strcmp(word, "win") && loadwins) {
  336.             load_window(s);
  337.         } else if (!strcmp(word, "tool") && loadwins) {
  338.             toolx = hexval(nextword(&s));
  339.             tooly = hexval(nextword(&s));
  340.             if (toolwindow && toolwindow->wi_handle >= 0) {
  341.                 close_window(toolwindow);
  342.                 toolwindow->wi_x = toolx;
  343.                 toolwindow->wi_y = tooly;
  344.                 open_window(toolwindow);
  345.             }
  346.         }
  347. endloop: ;
  348.     }
  349.  
  350. /* reset the global menu */
  351.     for (e = globalmenu->contents; e; e = e->next) {
  352.         if (e->func == toggle
  353. #ifdef GLOBL_APPL_MENUS
  354.          || e->func == togglemenu
  355. #endif
  356.         ) {
  357.             var = e->arg;
  358.             if (*var)
  359.                 check_entry(globalmenu, e);
  360.             else
  361.                 uncheck_entry(globalmenu, e);
  362.         }
  363.     }
  364.  
  365.     if (lineAset)
  366.         set_linea(stdcol, stdrow);
  367.     FBclose(f);
  368.     graf_mouse(ARROW, 0L);
  369. }
  370.  
  371. static int
  372. strwrite(fd, s)
  373.     int fd;
  374.     char *s;
  375. {
  376.     long r = strlen(s);
  377.  
  378.     return Fwrite(fd, r, s);
  379. }
  380.  
  381. static void
  382. strwritex(fd, s)
  383.     int fd;
  384.     char *s;
  385. {
  386.     strwrite(fd, s);
  387.     strwrite(fd, " ");
  388. }
  389.  
  390. static int
  391. quotewrite(fd, s)
  392.     int fd;
  393.     char *s;
  394. {
  395.     int nbytes;
  396.     char buf[WORDSIZ];
  397.     char c;
  398.  
  399.     buf[0] = QUOTE;
  400.     for (nbytes = 1; nbytes < WORDSIZ-2; nbytes++) {
  401.         c = *s++;
  402.         if (!c) break;
  403.         else if (c == QUOTE)
  404.             c = '\'';
  405.         buf[nbytes] = c;
  406.     }
  407.     buf[nbytes] = QUOTE;
  408.     return Fwrite(fd, (long)nbytes+1, buf);
  409. }
  410.  
  411. void
  412. save_config(file)
  413.     char *file;
  414. {
  415.     int fd, i;
  416.     struct varstruct *v;
  417.     static char name[128];
  418.     MENU *m;
  419.     ENTRY *e;
  420.     int savewins = 0;
  421.     WINDOW *w;
  422.     TEXTWIN *t;
  423.  
  424.     if (!file) {
  425.         file = name;
  426.         i = getfilename(Strng(SAVECFG), name, config_path,
  427.             config_name);
  428.         if (i != OK) return;
  429.         if (gl_winlist) {
  430.             i = form_alert(1, AlertStrng(SAVWPOS));
  431.             if (i == 1) savewins = 1;
  432.         }
  433.     }
  434.  
  435.     fd = Fcreate(file, 0);
  436.     if (fd <= 0) {
  437.         form_alert(1, AlertStrng(UNABLE1));
  438.         return;
  439.     }
  440.     for (v = vars; v->name; v++) {
  441.         if (!strncmp(v->name, "std", 3)) continue;
  442.         strwrite(fd, v->name);
  443.         strwrite(fd, " ");
  444.         strwrite(fd, valhex(*v->addr));
  445.         strwrite(fd, "\r\n");
  446.     }
  447.     if (lineAset) {
  448.         strwrite(fd, "stdcol "); strwrite(fd, valhex(stdcol));
  449.         strwrite(fd, "\r\nstdrow ");
  450.         strwrite(fd, valhex(stdrow));
  451.         strwrite(fd, "\r\n");
  452.     }
  453.     strwrite(fd, "font ");
  454.     strwritex(fd, valhex(default_font));
  455.     strwrite(fd, valhex(default_height)); strwrite(fd, "\r\n");
  456.  
  457.     if (*progpath) {
  458.         strwrite(fd, "path ");
  459.         strwrite(fd, progpath);
  460.         strwrite(fd, "\r\n");
  461.         if (*dfltprog) {
  462.             strwrite(fd, "prog ");
  463.             strwrite(fd, dfltprog);
  464.             strwrite(fd, "\r\n");
  465.         }
  466.     }
  467.  
  468.     strwrite(fd, "menu ");
  469.     for (m = sysbar; m != LASTMENU; m = m->next) {
  470.         for (e = m->contents; e; e = e->next) {
  471.             if (e->entry[0] != '-') {
  472.                 strwritex(fd, valhex(e->keycode));
  473.             }
  474.         }
  475.     }
  476.     strwrite(fd, "\r\n");
  477.  
  478.     if (savewins) {
  479.         strwrite(fd, "tool ");
  480.         strwritex(fd, valhex(toolx));
  481.         strwrite(fd, valhex(tooly));
  482.         strwrite(fd, "\r\n");
  483.  
  484.         for (w = gl_winlist; w; w = w->next) {
  485.             if (w->wtype != TEXT_WIN) continue;
  486.             t = w->extra;
  487.             strwrite(fd, "win ");
  488.             strwritex(fd, valhex(w->flags));
  489.             if (w->flags & WICONIFIED) {
  490.                 strwritex(fd, valhex(w->old_wkind));
  491.                 strwritex(fd, valhex(w->prevx));
  492.                 strwritex(fd, valhex(w->prevy));
  493.                 strwritex(fd, valhex(w->prevw));
  494.                 strwritex(fd, valhex(w->prevh));
  495.             } else {
  496.                 strwritex(fd, valhex(w->wi_kind));
  497.                 strwritex(fd, valhex(w->wi_x));
  498.                 strwritex(fd, valhex(w->wi_y));
  499.                 strwritex(fd, valhex(w->wi_w));
  500.                 strwritex(fd, valhex(w->wi_h));
  501.             }
  502.             strwritex(fd, valhex(NCOLS(t)));
  503.             strwritex(fd, valhex(NROWS(t)));
  504.             strwritex(fd, valhex(t->cfont));
  505.             strwritex(fd, valhex(t->cpoints));
  506.             quotewrite(fd, w->wi_title); strwrite(fd, " ");
  507.             strwritex(fd, t->prog);
  508.             quotewrite(fd, t->cmdlin); strwrite(fd, " ");
  509.             strwritex(fd, t->progdir);
  510.             strwrite(fd, valhex(SCROLLBACK(t)));
  511.             strwrite(fd, "\r\n");
  512.         }
  513.     }
  514.  
  515.     (void)Fclose(fd);
  516. }
  517.  
  518.  
  519. /*
  520.  * menu configuration routines
  521.  */
  522.  
  523. void
  524. load_menu_key(s)
  525.     char *s;
  526. {
  527.     MENU *m;
  528.     ENTRY *e;
  529.  
  530.     m = sysbar;
  531.     e = m->contents;
  532.     for(;;) {
  533.         if (e->entry[0] != '-') {
  534.             e->keycode = hexval(nextword(&s));
  535.         }
  536.         e = e->next;
  537.         if (!e) {
  538.             m = m->next;
  539.             if (m == LASTMENU) break;
  540.             e = m->contents;
  541.         }
  542.     }
  543.     show_menu(sysbar);
  544. }
  545.  
  546. void
  547. config_menu()
  548. {
  549.     int r;
  550.     int x, y, w, h;
  551.     int dummy, mx, my, keycode;
  552.     int done, event, mbreturn;
  553.     int atstart = 1;
  554.     MENU *m, *lastm;
  555.     ENTRY *e, *laste;
  556.     int change;
  557.  
  558.     wind_update(BEG_MCTRL);
  559.     form_center(menudef_dialog, &x, &y, &w, &h);
  560.     form_dial(FMD_START, 0, 0, 32, 32, x, y, w, h);
  561.     if (win_flourishes)
  562.         form_dial(FMD_GROW, 0, 0, 32, 32, x, y, w, h);
  563.  
  564.     objc_draw(menudef_dialog, 0, 1, x, y, w, h);
  565.  
  566.     lastm = 0; laste = 0;
  567.     m = sysbar;
  568.     e = m->contents;
  569.     done = 0;
  570.     change = 1;
  571.  
  572.     do {
  573.         if (change) {
  574.             if (atstart) {
  575.                 if (menudef_dialog[MDPREV].ob_state != DISABLED)
  576.                     objc_change(menudef_dialog, MDPREV, 0,
  577.                         x, y, w, h, DISABLED, 1);
  578.             } else {
  579.                 if (menudef_dialog[MDPREV].ob_state != NORMAL)
  580.                     objc_change(menudef_dialog, MDPREV, 0,
  581.                         x, y, w, h, NORMAL, 1);
  582.             }
  583.             if (e->next == 0 && m->next == LASTMENU) {
  584.                 if (menudef_dialog[MDNEXT].ob_state != DISABLED)
  585.                     objc_change(menudef_dialog, MDNEXT, 0,
  586.                         x, y, w, h, DISABLED, 1);
  587.             } else {
  588.                 if (menudef_dialog[MDNEXT].ob_state != NORMAL)
  589.                     objc_change(menudef_dialog, MDNEXT, 0,
  590.                         x, y, w, h, NORMAL, 1);
  591.             }
  592.             menudef_dialog[MENUSTR].ob_spec = (long)m->title;
  593.             menudef_dialog[ENTRYSTR].ob_spec = (long)e->entry;
  594.             menudef_dialog[ASCIISTR].ob_spec = (long)UNALT(e->keycode);
  595.             menudef_dialog[HEXSTR].ob_spec = (long)valhex(e->keycode);
  596.  
  597.             objc_draw(menudef_dialog, MENUFRAM, 2, x, y, w, h);
  598.             objc_draw(menudef_dialog, KEYFRAM, 2, x, y, w, h);
  599.         }
  600.         change = 0;
  601.  
  602.         event = evnt_multi(MU_BUTTON|MU_KEYBD,
  603.             0x0002, 0x0001, 0x0001,
  604.             0, 0, 0, 0, 0,
  605.             0, 0, 0, 0, 0,
  606.             0L, 0L,
  607.             &mx, &my, &dummy, &dummy,
  608.             &keycode, &mbreturn);
  609.  
  610.         if (event & MU_KEYBD) {
  611.             change = 1;
  612.             if ((keycode & 0x00ff) == ' ')
  613.                 e->keycode = 0;
  614.             else if (keycode == 0x1c0d) {
  615.         /* RETURN key pressed -- exit dialog */
  616.                 done = 1;
  617.             } else {
  618.                 e->keycode = keycode;
  619.             }
  620. #if 0
  621.             if (!(event & MU_BUTTON))
  622.                 goto advance;
  623. #endif
  624.         }
  625.         if (event & MU_BUTTON) {
  626.             r = objc_find(menudef_dialog, 0, 2, mx, my);
  627.             if (r == MDNEXT || r == MDPREV) {
  628.                 if (menudef_dialog[r].ob_state == DISABLED) {
  629.                     continue;
  630.                 }
  631.                 evnt_timer(50L);
  632.             }
  633.             switch (r) {
  634.             case MDNEXT:
  635.         advance:
  636.                 atstart = 0;
  637.                 if (e->next) {
  638.                     e = e->next;
  639.                 } else if (m->next != LASTMENU) {
  640.                     m = m->next;
  641.                     e = m->contents;
  642.                 } else if (event & MU_KEYBD) {
  643.                     done = 1;
  644.                 } else {
  645.                     (void)Bconout(2, 7);
  646.                 }
  647.                 if (e->entry[0] == '-')
  648.                     goto advance;
  649.                 change = 1;
  650.                 break;
  651.             case MDPREV:
  652.         retreat:
  653.                 if (atstart) {
  654.                     (void)Bconout(2, 7);
  655.                 } else {
  656.                     if (m->contents == e) {
  657.                         laste = 0;
  658.                         if (sysbar == m)
  659.                             lastm = 0;
  660.                         else {
  661.                             lastm = sysbar;
  662.                             while (m != lastm->next)
  663.                                 lastm = lastm->next;
  664.                         }
  665.                     } else {
  666.                         lastm = m;
  667.                         laste = m->contents;
  668.                         while (laste->next != e)
  669.                             laste = laste->next;
  670.                     }
  671.  
  672.                     m = (lastm) ? lastm : sysbar;
  673.                     if (laste)
  674.                         e = laste;
  675.                     else
  676.                         for (e = m->contents; e->next; )
  677.                             e = e->next;
  678.                 }
  679.                 if (m == sysbar && e == m->contents)
  680.                     atstart = 1;
  681.                 if (e->entry[0] == '-') goto retreat;
  682.                 change = 1;
  683.                 break;
  684.             case MDDONE:
  685.                 done = 1; break;
  686.             default:
  687.                 (void)Bconout(2, 7);
  688.             }
  689.         }
  690.     } while (!done);
  691.  
  692.     if (win_flourishes)
  693.         form_dial(FMD_SHRINK, 0, 0, 32, 32, x, y, w, h);
  694.     form_dial(FMD_FINISH, 0, 0, 32, 32, x, y, w, h);
  695.     wind_update(END_MCTRL);
  696.     show_menu(sysbar);
  697. }
  698.  
  699. /*
  700.  * loadable menu support:
  701.  * loadmenu(fname): load the .MNU file corresponding to the program 'fname'
  702.  */
  703.  
  704. void
  705. sendhex(s)
  706.     char *s;
  707. {
  708.     WINDOW *w;
  709.     static char pbuf[5];
  710.     char *t;
  711.     int i, c;
  712.  
  713.     if (!gl_topwin) return;
  714.     w = gl_topwin;
  715.  
  716.     i = 0; t = pbuf;
  717.  
  718.     for(;;) {
  719.         if (!*s) break;
  720.         *t++ = *s++;
  721.         i++;
  722.         if (i == 4) {
  723.             c = hexval(pbuf);
  724.             if (!c) break;
  725.             i = 0;
  726.             t = pbuf;
  727.             (*w->keyinp)(w, c, 0);
  728.         }
  729.     }
  730. }
  731.  
  732. MENU *
  733. loadmenu(fname)
  734.     char *fname;
  735. {
  736.     static char pname[LINSIZ];
  737.     char *s, *lastdot, c;
  738.     FILBUF *f;
  739.     MENU *bar, *m, **last;
  740.     int keycode;
  741.     char *name, *data;
  742.  
  743. #ifndef GLOBAL_APPL_MENUS
  744. /* appl_menus now controls whether to load menus at all */
  745.     if (!appl_menus)
  746.         return 0;
  747. #endif
  748.     s = pname;
  749.     while (*s++ = *fname++) ;
  750.     --s;
  751.  
  752.     lastdot = s;
  753.     while (s >= pname && (c = *s) != '\\') {
  754.         if (c == '.') lastdot = s;
  755.         --s;
  756.     }
  757.  
  758.     *lastdot++ = '.';
  759.     *lastdot++ = 'M'; *lastdot++ = 'N'; *lastdot++ = 'U';
  760.     *lastdot = 0;
  761.  
  762.     f = FBopen(pname);
  763.     if (!f) return 0;
  764.  
  765.     last = &bar;
  766.     bar = m = 0;
  767.     for(;;) {
  768.         if (!FBgets(f, pname, LINSIZ)) break;
  769.         s = pname;
  770.         if (!isspace(*s)) {
  771.             m = create_menu(pname);
  772.             if (!m) break;
  773.             *last = m;
  774.             last = &m->next;
  775.         } else {
  776.             while (*s && isspace(*s)) s++;
  777.             if (!*s) continue;
  778.             name = strdup(nextword(&s));
  779.             data = strdup(nextword(&s));
  780.             keycode = hexval(nextword(&s));
  781.             if (name[0] == '-')
  782.                 add_entry(m, name, sendhex, data, keycode, DISABLED);
  783.             else
  784.                 add_entry(m, name, sendhex, data, keycode, NORMAL);
  785.         }
  786.     }
  787.     FBclose(f);
  788.     return bar;
  789. }
  790.  
  791. void
  792. unloadmenu(men)
  793.     MENU *men;
  794. {
  795.     ENTRY *e;
  796.     MENU *m;
  797.  
  798.  
  799.     for (m = men; m; m = m->next) {
  800.         for (e = m->contents; e; e = e->next) {
  801.             if (e->arg)
  802.                 free(e->arg);
  803.         }
  804.     }
  805.     destroy_menu(men);
  806. }
  807.